package export;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.jplus.core.db.JdbcTemplate;
import com.jplus.core.plugin.scheduling.cron.ScheduledTask;
import com.jplus.core.utill.HttpClientUtil;
import com.jplus.core.utill.HttpClientUtil.RequestMethod;
import com.jplus.core.utill.JSON;
import com.jplus.core.utill.JSON.JSONArray;
import com.jplus.core.utill.JSON.JSONObject;
import com.jplus.core.utill.JUtil;
import com.jplus.core.utill.LRUCache;
import com.jplus.core.utill.SimpleSql;
import com.jplus.mvc.util.Base64Util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RunshExport {
	static Logger log = LoggerFactory.getLogger(RunshExport.class);
	// 缓存
	private final LRUCache<String, String> LRUCACHE = new LRUCache<String, String>(16);

	String code = "shhr";
	String keyFactor = "B3B34B9635DB2AE4";
	String imgUrl = "http://runsh.unovo.com.cn/";
	String host;

	Properties prop = new Properties();
	JdbcTemplate runsh;
	SimpleSql sql;

	void init() throws IOException, ClassNotFoundException {
		prop.load(new FileInputStream(new File("D:/config/LY_PRD_JDBC.properties")));
		runsh = new JdbcTemplate(GET(prop, "runsh.jdbcurl"), GET(prop, "runsh.user"), GET(prop, "runsh.pass"));
		sql = new SimpleSql("simple.sql");
		host = GET(prop, "runsh.hosturl");
	}

	public static void main(String[] args) throws Exception {
		final RunshExport run = new RunshExport();
		run.init();
		run.push(24 * 3);
		ScheduledTask task = new ScheduledTask("30 0/10 * * * ?") {
			@Override
			public void invokeMethod() {
				run.push(1);
			}
		};
		// task.setDaemon(true);
		task.start();
	}

	/*
	 * 同步人脸照片到润生活
	 */
	public void push(long hour) {
		try {
			SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String date = sdf2.format(new Date(new Date().getTime() - (long) (1000 * 60 * 60) * hour)); // 获取当前时间前2个小时内数据
			System.out.println("");
			log.info(">> 时间范围>" + date);
			// log.info("1.2获取应用批次号：" + readSysBatch());
			String res = readEqu();
			JSONArray jsona = JSON.parseObject(res).getJSONArray("reContent");
			List<String[]> equSn = new ArrayList<>();
			for (int i = 0; i < jsona.size(); i++) {
				JSONObject jobj = jsona.getJSONObject(i);
				if (jobj.getString("equName").indexOf("脸") > 0)
					equSn.add(new String[] { jobj.getString("equSn"), jobj.getString("merCode") });
			}
			log.info("1.3设备获取_ 增量：" + readEqu());

			// log.info("1.4根据序列号获取设备:" + pf.findByEquSn());
			// log.info("1.7获取访客刷人脸数据:" + pf.findVisEvent());
			// log.info("1.8获取业主刷人脸数据:" + pf.findAccEvent());

			// log.info("1.5用户信息维护:" + pf.offSaveOrUp());
			// log.info("1.9权限注册注销：" + pf.powerSave());
			log.info(JSON.toJSONString(equSn));
			registerPerson(date, equSn);
			deletePerson(date, equSn);
		} catch (Exception e) {
			log.error("ERROR:", e);
		} finally {
			log.info("LRUCache.size:" + LRUCACHE.size());
		}
	}

	/**
	 * 1.2获取应用批次号
	 */
	public String readSysBatch() throws Exception {
		String url = host + "huaelComm_readSysBatch";
		JSONObject jobj = buildJSON();
		jobj.put("batchCodes", "10");
		return doPost(jobj, url, CT.FORM);
	}

	/**
	 * 1.3设备获取_ 增量
	 */
	public String readEqu() throws Exception {
		String url = host + "huaelComm_readEqu";
		JSONObject jobj = buildJSON();
		jobj.put("area", 0);
		jobj.put("batch", 0);
		jobj.put("num", 100);
		return doPost(jobj, url, CT.FORM);
	}

	/**
	 * 1.4根据序列号获取设备
	 */
	public String findByEquSn(String equSn) throws Exception {
		String url = host + "huaelHR_findByEquSn";
		JSONObject jobj = buildJSON();
		jobj.put("equSn", equSn);
		return doPost(jobj, url, CT.FORM);
	}

	/**
	 * 1.7获取访客刷人脸数据
	 */
	public String findVisEvent() throws Exception {
		String url = host + "huaelHR_findVisEvent";
		JSONObject jobj = buildJSON();
		jobj.put("batch", 0);
		jobj.put("num", 100);
		jobj.put("areaId", 0);
		return doPost(jobj, url, CT.BODY);
	}

	/**
	 * 1.8获取业主刷人脸数据
	 */
	public String findAccEvent() throws Exception {
		String url = host + "huaelHR_findVisEvent";
		JSONObject jobj = buildJSON();
		jobj.put("batch", 0);
		jobj.put("num", 100);
		jobj.put("areaId", 0);
		return doPost(jobj, url, CT.BODY);
	}

	/**
	 * 注册人脸
	 */
	public void registerPerson(String date, List<String[]> equsn) {
		List<PersonInfo> list = runsh.queryListBean(sql.get("listPersonPicAdd"), PersonInfo.class, date);
		if (!list.isEmpty()) {
			int size = list.size();
			log.info("总计：" + size);
			for (int i = 0; i < size; i++) {
				PersonInfo info = list.get(i);
				try {
					log.info("[{}/{}]{}", i + 1, size, info.toString());
					log.info("1.5用户信息维护:" + checkSucc(offSaveOrUp(info, true)));
					for (String[] td : equsn) {
						log.info("1.9权限注册：" + checkSucc(powerSave(info, td, true)));
					}
				} catch (Exception e) {
					log.error("ERROR:", e);
					// File url = new
					// File(getClass().getClassLoader().getResource("Fail.txt").getFile());
					// appendFile(url, info.toString());
				}
			}
		} else
			log.warn("[ADD] There is no personnel information change now");
	}

	/**
	 * 删除人脸
	 */
	public void deletePerson(String date, List<String[]> equsn) {
		List<PersonInfo> list = runsh.queryListBean(sql.get("listPersonPicDel"), PersonInfo.class, date);
		if (!list.isEmpty()) {
			int size = list.size();
			log.info("总计：" + size);
			for (int i = 0; i < size; i++) {
				PersonInfo info = list.get(i);
				try {
					log.info("[{}/{}]{}", i + 1, size, info.toString());
					for (String[] td : equsn) {
						log.info("1.9权限删除：" + checkSucc(powerSave(info, td, false)));
					}
					// log.info("1.5用户信息删除:" + checkSucc(offSaveOrUp(info,false)));

				} catch (Exception e) {
					log.error("ERROR:", e);
					// File url = new
					// File(getClass().getClassLoader().getResource("Fail.txt").getFile());
					// appendFile(url, info.toString());
				}
			}
		} else
			log.warn("[DEL] There is no personnel information change now");
	}

	String GET(Properties prop, String key) {
		return prop.getProperty(key).trim();
	}

	// 提交方式
	public static enum CT {
		FORM, BODY;
	}

	public static class PersonInfo {
		public String cardPic;
		public String facePic;
		public String idNo;
		public String customerId;
		public String customerName;
		// public String id ;
		// public String name ;
		public String mobile;
		public String sex;

		public String createTime;

		@Override
		public String toString() {
			return JSON.toJSONString(this);
		}

		public PersonInfo() {
		}

	}

	public static void appendFile(File fileName, String content) {
		try {
			FileWriter writer = new FileWriter(fileName, true);
			writer.write(content);
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private String checkSucc(String res) throws Exception {
		// JSONObject jobj = JSON.parseObject(res);
		// if (!jobj.getString("reCode").equals("000000"))
		// throw new Exception("Fail");
		return res;
	}

	/**
	 * 1.5用户信息维护
	 * 
	 * @throws Exception
	 */
	public String offSaveOrUp(PersonInfo info, boolean state) throws Exception {
		String url = host + "huaelHR_offSaveOrUp";
		JSONObject jobj = buildJSON();
		JSONArray faces = new JSONArray();
		JSONObject face = new JSONObject();
		face.put("offCode", info.customerId);
		face.put("offName", info.customerName);
		int sex = "1048001".equals(info.sex) ? 0 : 1;
		face.put("offSex", sex);// 0男1女
		face.put("offState", state ? "1" : "2");// 0:添加;1:添加存在修改;2:删除”(String)必填

		face.put("picture1", getPic(info));
		face.put("picture2", "");
		face.put("picture3", "");
		face.put("picture4", "");
		face.put("picture5", "");

		face.put("offLoginName", "");
		face.put("deptFullName", "用户");
		face.put("offType", "业主");
		face.put("offBirth", "");
		face.put("offInside", "");
		face.put("offMobile ", "");
		face.put("offLoginPs", "");
		face.put("offPassword", "");
		face.put("offIdent", "");
		face.put("offIdentCode", "");
		face.put("offEmail", "");
		face.put("offAddr", "");
		face.put("offCard", "");
		face.put("offSecCard", "");
		face.put("offThrCard", "");
		faces.add(face);
		jobj.put("content", faces);
		return doPost(jobj, url, CT.BODY);
	}

	/**
	 * 1.9权限注册注销
	 * 
	 * @throws Exception
	 */
	public String powerSave(PersonInfo info, String[] td, boolean state) throws Exception {
		String url = host + "huaelHR_powerSave";
		JSONObject jobj = buildJSON();
		JSONArray faces = new JSONArray();
		{
			JSONObject face = new JSONObject();
			face.put("offCode", info.customerId);
			face.put("state", state ? "1" : "5");// 1注册5注销

			face.put("equSn", td[0]);// 设备序列号”(String)必填 对应1.3接口
			face.put("merCode", td[1]);
			face.put("equType", "1");// ”1门禁2考勤8消费”(String)必填 对应1.3接口
			face.put("picture1", getPic(info));
			// face.put("picture1", "");

			face.put("startTime", "");
			face.put("endTime", "");

			faces.add(face);
		}
		jobj.put("content", faces);
		return doPost(jobj, url, CT.BODY);
	}

	public JSONObject buildJSON() {
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");// 单线程
		String time = sdf.format(date);
		JSONObject jobj = new JSONObject();
		jobj.put("code", code);
		jobj.put("time", time);
		jobj.put("keyt", encodeMd5(code + time + keyFactor).toUpperCase());
		return jobj;
	}

	private String getPic(PersonInfo info) throws Exception {
		HttpClientUtil http = new HttpClientUtil();
		String path = imgUrl + info.facePic;
		String res = LRUCACHE.get(path, (String key) -> {
			InputStream is = http.doRequest(path, null, RequestMethod.GET);
			return Base64Util.encode(http.toByteArray(is));
		});
		return res;

	}

	private String doPost(JSONObject jobj, String url, CT ct) {
		HttpClientUtil http = new HttpClientUtil();
		http.setTimeout(1000 * 20);// 秒钟
		System.err.println(url);
		if (ct == CT.FORM) {// form commit
			Map<String, Object> param = new HashMap<>();
			param.put("data", jobj.toJSONString());
			log.info("Param:{}", param);
			return http.doPost(url, param);
		}
		if (ct == CT.BODY) {// body commit
			String param = jobj.toJSONString();
			jobj.getJSONArray("content").getJSONObject(0).put("picture1", "[BASE64]");
			log.info("Param:{}", jobj);
			http.setHeader("Content-Type", "application/json");
			return http.doPost(url, param);
		}
		return null;
	}

	// == Encode======================
	public String encodeMd5(String str) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(str.getBytes());
			String res = new BigInteger(1, md.digest()).toString(16);
			return JUtil.getPadStr(32 - res.length(), "0") + res;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}
